/**
 * 
 */
package Domain;
import java.util.*;

import Domain.RegexParser;
/**
 * @author gth854p
 *
 */
public class RegexParser {
	LinkedList<String> expandedRegex,operators,tokens;
	LinkedHashMap<String,DefinedClass> lex;
	int peekIndex;
	
	public RegexParser()
	{
		operators = new LinkedList<String>();
		operators.add("OPENBRACK");
		operators.add("CLOSEBRACK");
		operators.add("PLUS");
		operators.add("STAR");
		operators.add("RANGE");
		operators.add("OPENPAR");
		operators.add("CLOSEPAR");
		operators.add("UNION");
		operators.add("EMPTY");
		peekIndex = 0;
		
	}
	public void setTokens(LinkedList<String> t)
	{
		this.tokens = t;
	}
	public void setDefinedClasses(LinkedHashMap<String,DefinedClass> l)
	{
		this.lex = l;
	}
	public static Set<String> getRange(String range)
	{
		int start,end;
		
		
		char[] temp2;
		
		String[] temp = range.split("-");
		Set<String> retval = new HashSet<String>();
		
		
		if(temp[0].startsWith("\\"))
			start = temp[0].charAt(1);
		else
			start = temp[0].charAt(0);
		if(temp[1].startsWith("\\"))
			end = temp[1].charAt(1);
		else
			end = temp[1].charAt(0);
		
		for(int i = start;i<end+1;i++)
		{
			
			if(i==92||i==94||i==91||i==93||i==45)
				{
					temp2 = new char[2];
					temp2[0] = '\\';
					temp2[1] = (char) i;
				}
			else
			{
				temp2  = new char[1];
				temp2[0] = (char) i;
			}
			
			retval.add(new String(temp2));
		}
		return retval;
	}
	
	public static boolean isCLS_Char(String compare)
	{
		char[] temp;
		for(int i = 33;i<127;i++)
		{
			
			
			if(i==92||i==94||i==91||i==93||i==45)
				{
					temp = new char[2];
					temp[0] = '\\';
					temp[1] = (char) i;
					if(compare.equals(new String(temp)))
						return true;
				}
			else
			{
				temp  = new char[1];
				temp[0] = (char) i;
				if(compare.equals(new String(temp)))
					return true;
			}
			
			
		}
		return false;
	}
	
	public static boolean isRange(String compare)
	{
		int start,end;
		char[] temp2;
		if(!compare.contains("-"))
			return false;
		String[] temp = compare.split("-",2);
		if(!RegexParser.isCLS_Char(temp[0]))
			return false;
		if(!RegexParser.isCLS_Char(temp[1]))
			return false;
		
		if(temp[0].startsWith("\\"))
			start = temp[0].charAt(1);
		else
			start = temp[0].charAt(0);
		if(temp[1].startsWith("\\"))
			end = temp[1].charAt(1);
		else
			end = temp[1].charAt(0);
		if(end<start)
			return false;
		
		return true;
		
	}
	public static boolean isCharSet(String compare)
	{
		if(RegexParser.isRange(compare))
			return true;
		if(RegexParser.isCLS_Char(compare))
			return true;
		return false;
	}
	public static LinkedList<String> expandTokens(String regex,LinkedHashMap<String,DefinedClass> lex)
	{
		LinkedList<String> expansion = new LinkedList<String>();
		String temp = "";
		
		//single out escaped chars
		for(int i = 0;i<regex.length();i++)
		{
			char[] chars;
			if(regex.charAt(i)=='\\')
			{
				chars = new char[2];
				chars[0] = regex.charAt(i);
				i += 1;
				chars[1] = regex.charAt(i);
				expansion.add(new String(chars));
			}
			else
			{
				
				chars = new char[1];
				chars[0] = regex.charAt(i);
				if(chars[0]>32&&chars[0]<127)
				expansion.add(new String(chars));
				
			}
			
		}
		//extract identifiers
		for(int i = 0;i<expansion.size();i++)
		{
			for(int j = expansion.size()-1;j>i;j--)
			{
				temp = "";
				for(int k = i;k<=j;k++)
				{
					temp += expansion.get(k);
				}
				if(lex.containsKey(temp))
				{
					expansion.set(i, temp);
					
					for(int k = j;k>i;k--)
					{
						//System.out.println("size = "+j+" removing"+expansion.get(k));
						expansion.remove(k);
						j--;
					}
				}
			}
		}
		boolean inBracket = false;
		int exclusion = 0;
		for(int i = 0;i<expansion.size();i++)
		{
			temp = expansion.get(i);
			if(temp.equals("["))
			{
				inBracket = true;
				expansion.set(i, "OPENBRACK");
				if(expansion.get(i+1).equals("^"))
				{
					expansion.set(i+1,"EXCLUSION"); i++;
					exclusion = 1;
				}
				continue;
			}
			if(temp.equals("]"))
			{
				
				inBracket = false;
				expansion.set(i, "CLOSEBRACK");
				
				if(exclusion==1)
				{
					i++;
					while(true)
					{
						if(expansion.get(i).equals("OPENBRACK")||lex.containsKey(expansion.get(i)))
						{
							i--;
							break;
						}
						if(expansion.get(i).equals("I")||expansion.get(i).equals("i"))
						{
							if(expansion.get(i+1).equals("N")||expansion.get(i+1).equals("n"))
							{
								expansion.set(i, "IN");
								expansion.remove(i+1);
								exclusion = 0;
								i++;
							}
							else
							{
								System.out.println("BFP"+expansion.get(i+1)+"BFP");
							}
						}
						else
						{
							expansion.remove(i);
						}
					}
					
				}
				continue;
			}
			if(temp.equals("*"))
			{
				if(!inBracket)
				{
					expansion.set(i, "STAR");
					if(i+1<expansion.size())
					{
						
						temp = expansion.get(i+1);
						if(!temp.equals(")")&&!temp.equals("|"))
						{
							expansion.add(i+1, "AND");
							i++;
							continue;
						}
						else
							temp = expansion.get(i);
					}
				}
				
				
			}
			if(temp.equals("+"))
			{
				if(!inBracket)
				{
					expansion.set(i, "PLUS");
					if(i+1<expansion.size())
					{
						
						temp = expansion.get(i+1);
						if(!temp.equals(")")&&!temp.equals("|"))
						{
							expansion.add(i+1, "AND");
							i++;
							continue;
						}
						else
							temp = expansion.get(i);
					}
				}
				
			}
			if(temp.equals("-"))
			{
				expansion.set(i, "RANGE");
				continue;
			}
			if(temp.equals("("))
			{
				expansion.set(i, "OPENPAR");
				continue;
			}
			if(temp.equals(")"))
			{
				expansion.set(i, "CLOSEPAR");
				if(i+1<expansion.size())
				{
					
					temp = expansion.get(i+1);
					if(!temp.equals("+")&&!temp.equals("|")&&!temp.equals("*")&&!temp.equals(")"))
					{
						expansion.add(i+1, "AND");
						i++;
						continue;
					}
				}
				continue;
			}
			if(temp.equals("|"))
			{
				String temp2 = expansion.get(i-1);
				String temp3 = expansion.get(i+1);
				expansion.set(i, "UNION");
				//if(temp2.charAt(0)>64&&temp2.charAt(0)<91)
				if(temp2.equals("OPENPAR"))
				{
					expansion.add(i, "EMPTY");
					i++;
				}
				if((temp3.charAt(0)>64&&temp3.charAt(0)<91)||(temp3.charAt(0)>96&&temp3.charAt(0)<123)||(temp3.charAt(0)==(new String("*").charAt(0)))||lex.containsKey(temp3)||(temp3.charAt(0)==(new String("+").charAt(0))))
				{
					
				}
				else
				{
					
					expansion.add(i+1, "EMPTY");
					i++;
				}
				continue;
			}
			if(expansion.size()>i+1&&(!expansion.get(i+1).equals(")"))&&(!expansion.get(i+1).equals("|"))&&(!expansion.get(i+1).equals("*"))&&(!expansion.get(i+1).equals("+"))&&(!expansion.get(i+1).equals("-")))
			{
				if(!inBracket)
				{
					expansion.add(i+1,"AND");
					i++;
				}
				else if(!expansion.get(i).equals("-")&&!expansion.get(i+1).equals("-")&&!expansion.get(i+1).equals("]"))
				{
					expansion.add(i+1,"UNION");
					i++;
					continue;
				}
				
			}
			/*if(inBracket)
			{
				
				if(!expansion.get(i+1).equals("-")&&!expansion.get(i+1).equals("]"))
				{
					expansion.add(i+1,"UNION");
					i++;
					continue;
				}
			}*/
		}
		Iterator<String> iter = expansion.iterator();
		
		
		return expansion;
	}
	public  class SyntaxTreeNode
	{
		private SyntaxTreeNode parent;
		private SyntaxTreeNode child;
		private LinkedList<RuleCommand> command;
		SyntaxTreeNode()
		{
			parent = null;
			child = null;
			command = new LinkedList<RuleCommand>();
		}
		SyntaxTreeNode getParent()
		{
			return parent;
		}
		void setParent(SyntaxTreeNode s)
		{
			this.parent = s;
		}
		SyntaxTreeNode getChild()
		{
			return child;
		}
		void setChild(SyntaxTreeNode s)
		{
			this.child = s;
		}
		void setCommand(LinkedList<RuleCommand> command) {
			this.command = command;
		}
		void addCommand(RuleCommand command) {
			this.command.add(command);
		}
		LinkedList<RuleCommand> getCommand() {
			return command;
		}
	}
	public RuleCommand orderOps(LinkedList<String> expansion,LinkedHashMap<String,DefinedClass> lex,RuleCommand root)
	{
		//handle not case first? if not that case, then
		//handle brackets first
		String token;
		LinkedList<RuleCommand> commandStack = new LinkedList<RuleCommand>();
		
		while(!expansion.isEmpty())
		{
			token = expansion.getFirst();
			
			if(token.equals("OPENPAR"))
			{
				//do check for the nots? if not that, then
				expansion.removeFirst();
				RuleCommand temp1 = null; 
				temp1 = orderOps(expansion,lex,temp1);
				if(expansion.isEmpty())
					return temp1;
				
				token = expansion.getFirst();
				//System.out.println("rc"+temp1.toString());
				if(token.equals("PLUS"))
				{
					expansion.removeFirst();
					PlusCommand temp = new PlusCommand();
					temp.setCommand(temp1);
					System.out.println("PLUS Exp");
					return temp;
				}
				else if(token.equals("STAR"))
				{
					expansion.removeFirst();
					StarCommand temp = new StarCommand();
					temp.setCommand(temp1);
					return temp;
				}
				else
					return temp1;
				//LinkedList<RuleCommand> temp = orderOps(expansion,lex);
				//temp.addAll(commandStack);
				//commandStack = temp;
			}
			else if(token.equals("CLOSEPAR"))
			{
				expansion.removeFirst();
				return root;
				
			}
			else if(token.equals("PLUS"))
			{
				
				expansion.removeFirst();
				PlusCommand temp = new PlusCommand();
				temp.setCommand(root);
				//System.out.println("PLUS Exp");
				root=temp;
			}
			else if(token.equals("STAR"))
			{
				
				expansion.removeFirst();
				StarCommand temp = new StarCommand();
				temp.setCommand(root);
				//System.out.println("Star Exp");
				root=temp;
				
			}
			else if(token.equals("UNION"))
			{
				
				expansion.removeFirst();
				UnionCommand temp = new UnionCommand();
				temp.setLeft(root);
				temp.setRight(orderOps(expansion,lex,null));
				//System.out.println("UNION Exp");
				root=temp;
				
			}
			else if(token.equals("AND"))
			{
				ANDCommand temp = new ANDCommand();
				temp.setLeft(root);
				expansion.removeFirst();
				temp.setRight(orderOps(expansion,lex,null));
				root=temp;
			}
			else if(lex.containsKey(token))
			{
				RuleCommand temp = lex.get(token);
				expansion.removeFirst();
				/*RuleCommand rc = orderOps(expansion,lex,dc);
				System.out.println("rc"+rc.toString());
				return rc;*/
				if(!expansion.isEmpty()&&expansion.getFirst().equals("STAR"))
				{
					expansion.removeFirst();
					StarCommand temp1 = new StarCommand();
					temp1.setCommand(temp);
					temp = temp1;
				}
				else if(!expansion.isEmpty()&&expansion.getFirst().equals("PLUS"))
				{
					expansion.removeFirst();
					PlusCommand temp1 = new PlusCommand();
					temp1.setCommand(temp);
					temp = temp1;
				}
				if(!expansion.isEmpty()&&expansion.getFirst().equals("AND"))
				{
					ANDCommand temp1 = new ANDCommand();
					temp1.setLeft(temp);
					expansion.removeFirst();
					temp = orderOps(expansion,lex,temp);
					temp1.setRight(temp);
					temp = temp1;
					
				}
				if(root==null)
					root = temp;
				else
					return temp;
				
			}
			else 
			{
				expansion.removeFirst();
				RuleCommand temp;
				if(token.startsWith("\\"))
				{
					
					temp = new ANDCommand();
					((ANDCommand)temp).setLeft(new RE_CharCommand(token.substring(0,1)));
					((ANDCommand)temp).setRight(new RE_CharCommand(token.substring(1,2)));		
				}
				else
					 temp = new RE_CharCommand(token);
				if(!expansion.isEmpty()&&expansion.getFirst().equals("STAR"))
				{
					expansion.removeFirst();
					StarCommand temp1 = new StarCommand();
					temp1.setCommand(temp);
					temp = temp1;
				}
				else if(!expansion.isEmpty()&&expansion.getFirst().equals("PLUS"))
				{
					expansion.removeFirst();
					PlusCommand temp1 = new PlusCommand();
					temp1.setCommand(temp);
					temp = temp1;
				}
				if(!expansion.isEmpty()&&expansion.getFirst().equals("AND"))
				{
					ANDCommand temp1 = new ANDCommand();
					temp1.setLeft(temp);
					expansion.removeFirst();
					temp = orderOps(expansion,lex,temp);
					temp1.setRight(temp);
					temp = temp1;
					
				}
				if(root==null)
					root = temp;
				else
					return temp;
				/*if(expansion.size()>1&&(!expansion.get(1).equals("UNION"))&&(!expansion.get(1).equals("CLOSEPAR"))&&(!expansion.get(1).equals("STAR"))&&(!expansion.get(1).equals("PLUS")))
				{
					commandStack.add(new ANDCommand());
				}*/
				
			}
		}
		return root;
	}
	public DefinedClass getDefinedClass(String regex,LinkedHashMap<String,DefinedClass> lex)
	{
		DefinedClass retval;
		String token;
		LinkedList<String> expansion = expandTokens(regex,lex);
		//System.out.println(expansion.size());
		HashSet<String> temp,temp2 = null;
		temp = new HashSet<String>();
		temp2 = new HashSet<String>();
		retval = new DefinedClass();
		token = expansion.getFirst();
		if(token.equals("OPENBRACK"))
		{
			//do check for the nots? if not that, then
			expansion.removeFirst();
			token = expansion.getFirst();
			if(token.equals("EXCLUSION"))
			{
				
				
				while(!token.equals("CLOSEBRACK"))
				{
					if(expansion.get(1).equals("RANGE"))
					{
						temp.addAll( (HashSet<String>) RegexParser.getRangeSet(token+"-"+expansion.get(2)));
						expansion.removeFirst();
						expansion.removeFirst();
						expansion.removeFirst();
						
					}
					else 
					{
						temp.add(token);
						expansion.removeFirst();
					}
					token = expansion.getFirst();		
						
				}
				//closebrack
				expansion.removeFirst();
				if(!expansion.removeFirst().equals("IN"))
				{
					System.out.println("EXCLUSION IN MISPLACED");
				}
				token = expansion.getFirst();
				if(token.equals("OPENBRACK"))
				{
					expansion.removeFirst();
					token = expansion.getFirst();
					while(!token.equals("CLOSEBRACK"))
					{
						if(expansion.get(1).equals("RANGE"))
						{
							temp2.addAll( (HashSet<String>) RegexParser.getRangeSet(token+"-"+expansion.get(2)));
							expansion.removeFirst();
							expansion.removeFirst();
							expansion.removeFirst();
							
						}
						else 
						{
							temp2.add(token);
							expansion.removeFirst();
						}
								
							
					}
					expansion.removeFirst();
				}
				else if(lex.containsKey(token))
				{
					temp2.addAll((HashSet<String>)(lex.get(token).getCharSet()));
				}
				
				temp2.removeAll(temp);
				retval.setCharSet(temp2);
				return retval;
			}
			else
			{
				
				while(!expansion.getFirst().equals("CLOSEBRACK"))
				{
					
					if(expansion.get(1).equals("RANGE"))
					{
						
						temp.addAll( (HashSet<String>) RegexParser.getRangeSet(expansion.get(0)+"-"+expansion.get(2)));
						expansion.removeFirst();
						expansion.removeFirst();
						expansion.removeFirst();
						
					}
					else
					{
						if(!expansion.getFirst().equals("UNION"))
							temp.add(expansion.getFirst());
						expansion.removeFirst();
					}
							
						
				}
				retval.setCharSet(temp);
				return retval;
				
			}
		
		}
		return retval;//a adefined class with an empty set
		
	}
	/*public static DefinedClass parseClass(String regex,LinkedHashMap<String,DefinedClass> lex)
	{
		LinkedList<String> expansion = new LinkedList<String>();
		//LinkedList<RuleCommand> stack = new LinkedList<RuleCommand>();
		DefinedClass retval = new DefinedClass();
		/*
		 * Any escaped characters are put into a single string. When creating NFAs, this will make sure they have the '-> \ -> (escaped char) ->' transitions
		 *
		for(int i = 0;i<regex.length();i++)
		{
			char[] chars;
			if(regex.charAt(i)=='\\')
			{
				chars = new char[2];
				chars[0] = regex.charAt(i);
				i += 1;
				chars[1] = regex.charAt(i);
				expansion.add(new String(chars));
			}
			else
			{
				chars = new char[1];
				chars[0] = regex.charAt(i);
				expansion.add(new String(chars));
				System.out.println("expansion:"+expansion.get(i));
			}
			
		}
		int index = 0;
		int endIndex;
		
			String compare = expansion.get(index+1);
			//System.out.println("Compare:"+compare+":");
			/*if(compare=="\\")
			{
				
			}
			else if(compare=="(")
			{
				
				//compare = parExpansion(expansion, index, compare);
				int parCount = 1;
				for(int j = index+1;j<expansion.size();j++)
				{
					if(expansion.get(j).equals("\\"))
						j +=2;
					else if(expansion.get(j).equals("("))
					{
						parCount += 1;
					}
					else if(expansion.get(j).equals(")"))
					{
						parCount -= 1;
						if(parCount==0)
						{
							compare = "";
							for(int k = index;k<j;j++)
							{
								compare.concat(expansion.remove(index));
							}
							RegexParser.parseClass(compare);
							//now handle * and +
							break;
						}
					}
						
				}
			}
			/**
			 
			
				//System.out.println("[");
				endIndex = index;
				endIndex = getEndBrackIndex(expansion, index, endIndex);
				
				String charset = "";
				for(int j = index+1; j<endIndex;j++)
					charset = charset.concat(expansion.get(j));
				
				HashSet<String> temp,temp2 = null;
				if(expansion.get(index+1).equals("^"))
				{
					//now a remove from operation
					index +=1;
					
					int startindex = index-1;
					if(charset.length()>2&&RegexParser.isRange(charset.substring(0,3)))
					{
						temp = (HashSet<String>) RegexParser.getRangeSet(charset.substring(1));
					}
					else
					{
						temp = new HashSet<String>();
						for(int j = index+1; j<endIndex;j++)
							temp.add(expansion.get(j));
					}
					index = endIndex+1;
					while(true)
					{
						if(!expansion.get(index).equals(" "))
							break;
						index++;
								
					}
					
					if(!(expansion.get(index)+expansion.get(index+1)).equals("IN"))
						return null;
					index += 2;
					while(true)
					{
						if(!expansion.get(index).equals(" "))
							break;
						index++;
								
					}
					if(expansion.get(index).equals("["))
					{
						
						endIndex = getEndBrackIndex(expansion, index, endIndex);
						charset = "";
						for(int j = index+1; j<endIndex;j++)
							charset = charset.concat(expansion.get(j));
						
						if(charset.length()>2&&RegexParser.isRange(charset.substring(0,3)))
						{
							temp2 = (HashSet<String>)RegexParser.getRangeSet(charset);
							
						}
						else
						{
							temp2 = new HashSet<String>();
							for(int j = index+1; j<endIndex;j++)
								temp2.add(expansion.get(j));
						}
						
						temp2.removeAll(temp); //now the char set
						retval.setCharSet(temp2);
						return retval;
						
					}
					else
					{
						//remove from a defined class
						charset = "";
						for(int j = index; j<expansion.size();j++)
							charset = charset.concat(expansion.get(j));
						if(lex.containsKey(charset))
							temp2 = (HashSet<String>) lex.get(charset).getCharSet();
						temp2.removeAll(temp); //now the char set
						retval.setCharSet(temp2);
						
						return retval;
					}
					
					//System.out.println("removing"+stack.get(0).createNFA()+stack.get(1).createNFA());
					
				}
				else if(charset.length()>2&&RegexParser.isRange(charset.substring(0,3)))
				{
					
					System.out.println("here: "+charset.substring(0,3));
					retval.setCharSet((HashSet<String>)RegexParser.getRangeSet(charset));
					return retval;
					
					
					
				}
				else
				{
					System.out.println("here");
					temp = new HashSet<String>();
					for(int j=index+1;j<endIndex;j++)
					{
						temp.add(expansion.get(j));
						
					}
					retval.setCharSet(temp);
					return retval;
				}
				
			
			
		
	}*/

	/*private static int getEndBrackIndex(LinkedList<String> expansion,
			int index, int endIndex) {
		for(int j = index+1;j<expansion.size();j++)
		{
			if(expansion.get(j).equals("\\"))
				j +=2;
			if(expansion.get(j).equals("]"))
			{
				//System.out.println("]");
				endIndex = j;
				break;
			}
				
		}
		return endIndex;
	}

	public static String parExpansion(LinkedList<String> expansion, int index, String compare) {
		int parCount = 1;
		for(int j = index+1;j<expansion.size();j++)
		{
			if(expansion.get(j)=="\\")
				j +=2;
			else if(expansion.get(j)=="(")
			{
				parCount += 1;
			}
			else if(expansion.get(j)==")")
			{
				parCount -= 1;
				if(parCount==0)
				{
					compare = "";
					for(int k = index;k<=j;j++)
					{
						compare.concat(expansion.remove(index));
						//RegexParser.parseClass(compare);
					}
					break;
				}
			}
				
		}
		return compare;
	}*/

	private static Set<String> getRangeSet(String charset) {
		Set<String> tempSet = new HashSet<String>();
		for(int j=charset.charAt(0);j<charset.charAt(2)+1;j++)
		{
			char[] temp = new char[1];
			temp[0] = (char)j;
			tempSet.add(new String(temp));
		}
		//System.out.println(charset.charAt(0)+":"+charset.charAt(2));
		return tempSet;
	}
	
	/*
	public String peekToken(){
		if(tokens.size()>0)
		return tokens.getFirst();
		else
			System.out.println("OUT");
		return "OUT";
	}
	public String peekToken(int k)
	{
		return tokens.get(k);
	}
	public void matchToken(String s){
		if(s.equals("EMPTY"))
			System.out.println(s);
		else if((tokens.size()>0)&&s.equals(tokens.getFirst()))
		{
			tokens.removeFirst();
			System.out.println(s);
		}
		else
			System.out.println("Match Error?");
	}
	
	
	public boolean regex(){
		//System.out.println("regex()");
		return (rexp1()&&rexpu());
	}
	public boolean rexpu(){
		String token;
		token = peekToken();
		boolean success = false;
		if(token.equals("UNION"))
		{
			matchToken(token);
			success = rexp1()&&rexpu();
			
			
		}
		else
		{
			matchToken("EMPTY");
			success = true;
		}
		return success;
		
	}
	public boolean rexp1(){
		return rexp2()&&rexp1u();
	}
	public boolean rexp1u()
	{
		
		boolean success = rexp2()&&rexp1u();
		if(!success)
		{
			matchToken("EMPTY");
			success = true;
		}
		return success;
	}
	public boolean rexp2(){
		String token;
		boolean success = false;
		token = peekToken();
		if(token.equals("OPENPAR"))
		{
			matchToken("OPENPAR");
			success = regex();
			matchToken("CLOSEPAR");
			success = (success&&rexp2tail());
		}
		if(!success && !this.operators.contains(token)&&(!lex.containsKey(token)))
		{
			matchToken(token);
			success = rexp2tail();
		}
		
		if(!success)
		{
			success = rexp3();
		}
		/*if(!success)
		{
			System.out.println(peekToken());
			matchToken("EMPTY");
			success = true;
		}
		
			return success;
	}
	public boolean rexp2tail()
	{
		if(peekToken().equals("STAR"))
		{
			matchToken("STAR");
			return true;
		}
		else if(peekToken().equals("PLUS"))
		{
			matchToken("PLUS");
			return true;
		}
		else
		{
			matchToken("EMPTY");
			return true;
		}
	}
	
	
	public boolean rexp3(){
		boolean success = false;
		
		success = charclass();
		
		if(!success)
		{
			matchToken("EMPTY");
			success = true;
		}
		return success;
			
		
	}
	public boolean charclass(){
		String token;
		token = peekToken();
		boolean success = false;
		if(!this.operators.contains(token)&&(!lex.containsKey(token)))
		{
			matchToken(token);
			success = true;
		}
		else if(!success&&token.equals("OPENBRACK"))
		{
			matchToken("OPENBRACK");
			success = charclass1();
		}
		else if(!success){
			matchToken(token);
			success = true;
		}
		return success;
	}
	public boolean charclass1(){
		
			return (charsetlist());//excludeset()
		
	}
	public boolean charsetlist()
	{
		boolean success=false;
		if(peekToken().equals("CLOSEBRACK"))
		{
			matchToken(peekToken());
			return true;
		}
		else
		{
			return charset()&&charsetlist();
		}
	}
	public boolean charset(){
		if(RegexParser.isCLS_Char(peekToken()))
		{
			matchToken(peekToken());
			return charsettail();
		}
		
		return false;
		
			
	}
	public boolean charsettail()
	{
		if(peekToken().equals("RANGE"))
		{
			matchToken("RANGE");
			matchToken(peekToken());
			return true;
		}
		else
		{
			matchToken("EMPTY");
			return true;
		}
	}
	public boolean range(){
		if(peekToken().equals("DASH"))
		{
			matchToken("DASH");
			matchToken("CLS_CHAR");
			matchToken("CLOSEBRACK");
			return true;
		}
		else
			return false;
		
	}
	public boolean excludeset(){
		boolean success = false;
		if(peekToken().equals("NOTCHAR"))
		{
			matchToken("NOTCHAR");
			success = charset();
			matchToken("CLOSEBRACK");
			matchToken("IN");
			success = (success&&excludesettail());
		}
		return success;
		
	}
	public boolean excludesettail(){
		boolean success = false;
		if(peekToken().equals("OPENBRACK"))
		{
			matchToken("OPENBRACK");
			success = charset();
			
		}
		else if(!success)
			success = definedClass();
		return success;
	}
	public boolean definedClass(){
		//matchToken("DEFINEDCLASS");
		return false;
	}
	*/
	
	public static void main(String[] args)
	{
		RegexParser parser = new RegexParser();
		LinkedHashMap<String,DefinedClass> lex = new LinkedHashMap<String,DefinedClass>();
		String testString = "\\*(A|DIGITIZED)*b+B*Cc\\*";
		DefinedClass s = new DefinedClass();
		lex.put("DIGIT", s);
		lex.put("DIGITIZED", s);
		
		LinkedList<String> expansion = RegexParser.expandTokens(testString, lex);
		
		parser.setTokens(expansion);
		parser.setDefinedClasses(lex);
		//parser.regex();
	}
}